﻿#region using statements

using System.Collections.Specialized;

using Microsoft.Xna.Framework;

using NGen.Collections;

using Nuclex.UserInterface.Controls;

#endregion

namespace NGen.Managers.GUI
{
	/// <summary>
	/// 	Delegate the reference type for which gui events can be created
	/// </summary>
	/// <param name = "p_guiEvent">the event message</param>
	public delegate void GUIMessageEventHandler(string p_guiEvent);

	public abstract class GUIElement
	{
		/// <summary>
		/// 	A collection of controls which are part of this GUIElement
		/// 	Observable collection allows it to be notified when controls
		/// 	are added or removed
		/// </summary>
		private readonly ObservableHashSet<Control> m_hsDisplayedChildren = new ObservableHashSet<Control>();

		/// <summary>
		/// 	Constructor, sets this GUIElement to be notified whenever a control
		/// 	is added or removed from its collection of children
		/// </summary>
		protected GUIElement() {
			m_hsDisplayedChildren.CollectionChanged += _OnGuiModified;
		}

		/// <summary>
		/// 	Property which mimicks the nuclex naming convention of nested 
		/// 	children within controls
		/// </summary>
		protected internal ObservableHashSet<Control> _Children {
			get { return m_hsDisplayedChildren; }
		}

		/// <summary>
		/// 	Event thrown to have the GUI notify other objects of gui interactions
		/// </summary>
		public event GUIMessageEventHandler GuiEvent;

		/// <summary>
		/// 	Allows child classes to throw the event
		/// 	(C# does not allow inheriting classes to throw inherited events
		/// 	of the parent)
		/// </summary>
		/// <param name = "p_guiEvent">string used to represent the gui event</param>
		public void ThrowGuiEvent(string p_guiEvent) {
			GuiEvent(p_guiEvent);
		}

		/// <summary>
		/// 	Function called whever a control is added or removed from the
		/// 	collection
		/// </summary>
		private void _OnGuiModified(object p_sender, NotifyCollectionChangedEventArgs p_e) {
			GameEngine.GetService<IManagerGUI>().RefreshGUI();
		}

		/// <summary>
		/// 	_Initialize the GUI
		/// </summary>
		protected internal abstract void _Initialize();

		/// <summary>
		/// 	Update values within the GUI
		/// </summary>
		/// <param name = "p_gameTime">snapshot of timing values</param>
		protected internal abstract void Update(GameTime p_gameTime);

		/// <summary>
		/// 	Draw the gui element
		/// </summary>
		/// <param name = "p_gameTime">snapshot of timing values</param>
		protected internal virtual void _Draw(GameTime p_gameTime) {}

		/// <summary>
		/// 	Cleanup the GUI
		/// </summary>
		protected internal abstract void _Cleanup();

		/// <summary>
		/// 	Override of toString to return the class name
		/// </summary>
		/// <returns>the name of this class</returns>
		public override sealed string ToString() {
			return GetType().Name;
		}
	}
}